#include <iostream>
#include <vector>

using namespace std;

struct LayerName
{
	char name[50];
};

//Check exist file?
int IsExist(char* filename)
{
	FILE* file = fopen(filename, "r");
	if(file)
	{
		fclose(file);
		return 1;
	}
	return 0;
}

//cut two space continous
int FindIndexTwoSpace ( char* str )
{
	int index = -1;
	for ( int i = 0; i < strlen ( str ); i++ )
		if ( str[i] == ' ' && str[i + 1] == ' ' )
		{
			index = i;
			break;
		}
	return index;
}
void CutTwoSpaceContinous ( char* str )
{
	int index = FindIndexTwoSpace ( str );
	while ( index != -1 )
	{
		for (int i = index; i < strlen( str ) - 1; i++)
			str[i] = str[i + 1];
		str[strlen( str ) - 1] = '\0';;
		
		index = FindIndexTwoSpace ( str );
	}
	cout << str << endl;
}

//cut space before of string
void CutSpaceBefore( char * str )
{
	while ( str[0] == ' ' )
	{
		for (int i = 0; i < strlen( str ) - 1; i++)
			str[i] = str[i + 1];
		str[strlen( str ) - 1] = '\0';
	}
}

char* Get_GtsFile ( char* gameFile )
{
	char line[200], temp[100], tempString[100];
	char* gtsFile;
	FILE* f = fopen ( gameFile, "r" );
	while ( !feof ( f ) )
	{
		fgets( line, sizeof ( line ), f );
		CutSpaceBefore ( line );
		if ( line[0] == 'L' && line[1] == 'O' && line[2] == 'A' && line[3] == 'D' && line[4] == '_' && line[5] == 'T' && line[6] == 'E' && line[7] == 'M' )
		{
			sscanf ( &line[0], "%s" "%s", &temp, & tempString );
			char _temp[50];		
			for (int i = strlen ( tempString ) - 2; i >= 0; i-- )
			{	
				if ( tempString[i] == '\\' )
				{
					_temp[strlen ( tempString ) - 2 - i] = '\0';
					break;
				}
				_temp[strlen ( tempString ) - 2 - i] = tempString[i];
			}

			for (int i = strlen ( _temp ) - 1; i >= 0; i-- )
			{	
				
				tempString[strlen ( _temp ) - 1 - i] = _temp[i];
			}
			tempString[strlen ( _temp ) ] = '\0';	
			
			gtsFile = new char [ strlen ( tempString )];
			strcpy ( gtsFile, tempString );
			break;

		}
		memset ( line, 0, sizeof ( line ) );
	}

	fclose ( f );
	return gtsFile;
}

char* Get_NamePackGuiFile ( char* gameFile )
{
	char name[50];
	int i;
	for ( i = 0; i < strlen ( gameFile ); i++ )
	{
		if ( gameFile[i] == '.' )
		{
			name[i] = gameFile[i];
			break;
		}
		name[i] = gameFile[i];
	}
	name[i + 1] = 'p';
	name[i + 2] = 'a';
	name[i + 3] = 'c';
	name[i + 4] = 'k';
	name[i + 5] = '\0';
	char* packName = new char ( strlen ( name ) );
	strcpy ( packName, name );

	return packName;
}

//read list 
vector <LayerName > GetLayerFileName ( char* gameFile )   
{
	vector < LayerName > layerList;

	char line[200], layerName[50], layerPath[256], _temp[100];
	FILE* f = fopen ( gameFile, "r");
	
	while ( !feof ( f ) )
	{
		fgets ( line, sizeof ( line ), f );
		if ( line[4] == 'L' && line[5] == 'O' && line[6] == 'A' && line[7] == 'D' && line[8] == '_' && line[9] == 'L' && line[10] == 'E' )
		{
			//sprite name
			sscanf ( &line[1], "%s" "%s", &_temp, &layerPath );
			char temp[50]; 
			for (int i = strlen ( layerPath ) - 2; i >= 0; i-- )
			{	
				if ( layerPath[i] == '\\' )
				{
					temp[strlen ( layerPath ) - 2 - i] = '\0';
					break;
				}
				temp[strlen ( layerPath ) - 2 - i] = layerPath[i];
			}

			for (int i = strlen ( temp ) - 1; i >= 0; i-- )
			{	
				
				layerName[strlen ( temp ) - 1 - i] = temp[i];
			}
			layerName[strlen ( temp ) ] = '\0';		

			//push			
			if ( IsExist ( layerName) )
			{
				LayerName _layerName;
				strcpy ( _layerName.name, strupr(layerName) );
				layerList.push_back ( _layerName );
			}
			else 
			{
				cout << endl <<  "------------  " << layerName << " not exist";
			}					
		}		

		memset ( line, 0, sizeof (line) );
		memset ( layerName, 0, sizeof (layerName) );
		memset ( layerPath, 0, sizeof (layerPath) );
	}

	fclose ( f );
	return layerList;
}

//get template ID from gui.gts
//return -1 if have not
int GetTemplateID ( char* gtsFile, char* _template )
{
	int countID = -1;
	char line[200], temp[100], tempString[100];
	FILE* f = fopen ( gtsFile, "r" );

	while ( !feof ( f ) )
	{
		fgets( line, sizeof ( line ), f );
		if ( line[0] == 'T' && line[1] == 'E' && line[2] == 'M' && line[3] == 'P' && line[4] == 'L' && line[5] == 'A' && line[6] == 'T' && line[7] == 'E')
		{
			countID++;
			sscanf ( &line[1], "%s" "%s" "%s", &temp, &temp, &tempString );
			//cut ""
			for (int i = 0; i < strlen ( tempString ) - 2; i++ )
				tempString[i] = tempString[i + 1];
			tempString[strlen ( tempString ) - 2] = '\0';
			if ( strcmp (tempString, _template) == 0 )
			{
				fclose ( f );
				return countID;	
			}
		
		}

		memset ( line, 0, sizeof ( line ) );
		memset ( line, 0, sizeof ( tempString ) );
	}

	fclose ( f );
	return -1;
}

//build template from gui.gts
void BuildTemplateID ( char* gtsFile )
{
	int countID = 0;
	char line[200], temp[100], tempString[100];
	FILE* f = fopen ( gtsFile, "r" );
	FILE* outF = fopen ( "GuiInclude.h", "w" );

	fprintf ( outF, "#ifndef GuiInclude_h" );
	fprintf ( outF, "\n#define GuiInclude_h" );
	fprintf ( outF, "\n\nclass GUI_TEMPLATE\n{\npublic:" );
	

	while ( !feof ( f ) )
	{
		fgets( line, sizeof ( line ), f );
		if ( line[0] == 'T' && line[1] == 'E' && line[2] == 'M' && line[3] == 'P' && line[4] == 'L' && line[5] == 'A' && line[6] == 'T' && line[7] == 'E')
		{			
			sscanf ( &line[1], "%s" "%s" "%s", &temp, &temp, &tempString );
			//cut ""
			for (int i = 0; i < strlen ( tempString ) - 2; i++ )
				tempString[i] = tempString[i + 1];
			tempString[strlen ( tempString ) - 2] = '\0';
			
			fprintf ( outF, "\n\tstatic const int %s = %d;", strupr(tempString), countID++ );
		}

		memset ( line, 0, sizeof ( line ) );
		memset ( line, 0, sizeof ( tempString ) );
	}

	fprintf ( outF, "\n\tstatic const int GUI_TEMPLATE_MAX = %d;\n};\n\n", countID ); 
	fclose ( f );
	fclose ( outF );
}

//buid GUI LAYER ID
void BuildGui_LayerID ( char* gameFile )
{
	vector < LayerName> layerNameList;
	char line[100], temp[20];
	layerNameList = GetLayerFileName ( gameFile );

	//camera
	FILE* f = fopen ( gameFile, "r" );
	FILE* outF = fopen ( "GuiInclude.h", "a" );

	fprintf ( outF, "\n\nclass GUI_LAYER\n{\npublic:" );

	//camera
	while ( !feof ( f ) )
	{
		fgets ( line , sizeof ( line ) , f );
		if ( line[8] == 'P' && line[9] == 'O' && line[10] == 'S' )
		{
			int xW, yH;
			sscanf ( &line[1], "%s" "%d" "%d", &temp, &xW, &yH );
			fprintf ( outF, "\n\tstatic const int cameraX = %d;", xW );
			fprintf ( outF, "\n\tstatic const int cameraY = %d;", yH );

			memset ( line, 0, sizeof ( line ) );
			fgets ( line , sizeof ( line ) , f );
			sscanf ( &line[1], "%s" "%d" "%d", &temp, &xW, &yH );
			fprintf ( outF, "\n\tstatic const int cameraW = %d;", xW );
			fprintf ( outF, "\n\tstatic const int cameraH = %d;", yH );
			memset ( line, 0, sizeof ( line ) );
			break;
		}
	}

	//layer
	int coutLayer = 0;
	char layerIDName[100];
	FILE* layerFile;
	for ( vector<LayerName>::iterator i = layerNameList.begin() ; i != layerNameList.end() ; i++ )
	{
		layerFile = fopen ( (*i).name, "r" );
		while ( !feof ( layerFile ) )
		{
			fgets ( line , sizeof ( line ), layerFile );
			CutSpaceBefore ( line );
			if ( line[0] == '\"' )
			{
				sscanf ( &line[0], "%s", &layerIDName );
				for ( int i = 0; i < strlen ( layerIDName ) - 2; i++ )
					layerIDName[i] = layerIDName[i + 1];
				layerIDName[strlen ( layerIDName ) - 2] = '\0';

				fprintf ( outF, "\n\tstatic const int %s = %d;", strupr ( layerIDName), coutLayer++ );
				memset ( line, 0, sizeof ( line ) );
				memset ( line, 0, sizeof ( layerIDName ) );
				fclose ( layerFile );
				layerFile = NULL;
				break;
			}
			memset ( line, 0, sizeof ( line ) );			
		}


		
	}
	fprintf ( outF, "\n\tstatic const int MAX_LAYER = %d;", coutLayer );
	fprintf ( outF, "\n};" );
	fclose ( f );
	fclose ( outF );

	
}

void BuildLevel ( char* gtsFile, char* levelFile )
{
	char line[100], elementID[100], temp[100];
	int countElememt = 0;

	FILE* f = fopen ( levelFile, "r" );
	FILE* outF = fopen ( "GuiInclude.h", "a" );

	while ( !feof ( f ) )
	{

		fgets ( line , sizeof ( line ), f );
		CutSpaceBefore( line );
		if ( line[0] == '\"' ) ////get class name
		{
			char layerIDName[100];
			sscanf ( &line[0], "%s", &layerIDName );
			for ( int i = 0; i < strlen ( layerIDName ) - 2; i++ )
				layerIDName[i] = layerIDName[i + 1];
			layerIDName[strlen ( layerIDName ) - 2] = '\0';

			fprintf ( outF, "\n\nclass LEVEL_%s\n{\npublic:", layerIDName);
			memset ( line, 0, sizeof ( line ) );
			memset ( line, 0, sizeof ( layerIDName ) );				
		}
		else if ( line[0] == 'L' && line[1] == 'A' && line[2] == 'Y' && line[3] == 'E' && line[4] == 'R' )
		{
			sscanf ( &line[0], "%s" "%s" "%s", &temp, &temp, &elementID );
			for ( int i = 1; i < strlen( elementID ); i++ )
			{
				if ( elementID[i] != '-' )
				{
					elementID[i - 1] = elementID[i];
				}
				else
				{
					elementID[i - 1] = '\0';
				}
			}

			if ( GetTemplateID ( gtsFile, elementID ) == -1 ) //not have to template 
				fprintf ( outF, "\n\tstatic const int %s = %d;", elementID, countElememt );
			else
				fprintf ( outF, "\n\tstatic const int %s_%d = %d;", elementID, countElememt, countElememt );
			countElememt++;
		}
		memset ( line , 0, sizeof ( line ) );
		memset ( line , 0, sizeof ( elementID ) );
	}
	fprintf ( outF, "\n\tstatic const int MAX_ELEMENT = %d;", countElememt );
	fprintf ( outF, "\n};" );
	fclose ( f );
	fclose ( outF );
}

//Build All level
void BuildAllLevel ( char* gameFile, char *gtsFile )
{
	vector < LayerName> layerNameList;
	layerNameList = GetLayerFileName ( gameFile );
	for ( vector<LayerName>::iterator i = layerNameList.begin() ; i != layerNameList.end() ; i++ )
	{
		cout << endl << "make LEVEL: " << (*i).name ;
		BuildLevel (gtsFile,  (*i).name );
	}

	FILE* outF = fopen ( "GuiInclude.h", "a" );
	fprintf ( outF, "\n\n#endif" );
	fclose ( outF );
}

//build gui to pack
void BuildGuiToPack ( char* gameFile )
{
	vector < LayerName> layerNameList;
	char line[100], temp[100];
	char* packName = Get_NamePackGuiFile ( gameFile );
	char* gtsFile = Get_GtsFile ( gameFile );

	layerNameList = GetLayerFileName ( gameFile );

	FILE* f = fopen ( gameFile, "r" );
	FILE* outF = fopen ( packName, "w" );

	for ( vector<LayerName>::iterator i = layerNameList.begin() ; i != layerNameList.end() ; i++ )
	{
		cout << endl << "packing LEVEL: " << (*i).name ;
		int countElement = 0;
		FILE* level = fopen ( (*i).name , "r" );
		while ( !feof ( level ) )
		{
			fgets ( line , sizeof ( line ) , level );
			CutSpaceBefore ( line );			
			if ( line[0] == 'L' && line[1] == 'A' && line[2] == 'Y' && line[3] == 'E' && line[4] == 'R' )
			{
				countElement++;
			}
			memset ( line , 0, sizeof ( line ) );
		}
		fprintf (outF, "ELEMENT %d\n", countElement );
		fclose ( level );
		level = fopen ( (*i).name , "r" );
		while ( !feof ( level ) )
		{
			fgets ( line , sizeof ( line ) , level );
			CutSpaceBefore ( line );			
			if ( line[0] == 'L' && line[1] == 'A' && line[2] == 'Y' && line[3] == 'E' && line[4] == 'R' )
			{
				int x = 0, y = 0, _template = 0;
				for ( int i = 0; i < 3; i++ )
				{
					memset ( line , 0, sizeof ( line ) );
					fgets ( line , sizeof ( line ) , level );
				}				
				memset ( line , 0, sizeof ( line ) );
				fgets ( line , sizeof ( line ) , level ); //pos
				sscanf ( &line[0], "%s" "%d" "%d", &temp, &x, &y );

				for ( int i = 0; i < 3; i++ )
				{
					memset ( line , 0, sizeof ( line ) );
					fgets ( line , sizeof ( line ) , level );
				}	

				memset ( line , 0, sizeof ( line ) );
				fgets ( line , sizeof ( line ) , level ); //template
				char tempType[50];
				sscanf ( &line[0], "%s" "%s" , &temp, &tempType );
				for ( int i = 0; i < strlen ( tempType ) - 2; i++ )
					tempType[i] = tempType[i + 1];
				tempType [strlen ( tempType ) - 2] = '\0';
				_template = GetTemplateID ( gtsFile, tempType );

				memset ( line , 0, sizeof ( line ) );
				fgets ( line , sizeof ( line ) , level ); //param
				//replace all by ' ' exception 1 -0
				for ( int i = 0; i < strlen ( line ); i ++ )
				{
					if ( !( line[i] >= '0' && line[i] <= '9' ) )
						line[i] = ' ';
				}
				CutTwoSpaceContinous ( line );
				fprintf ( outF, "%d %d %d %s\n", _template, x, y, line );
			}

			memset ( line , 0, sizeof ( line ) );
		}

		fclose ( level );
	}

	fclose ( f );
	fclose ( outF );


}


//build GUI
void BuildGui ( char* gameFile )
{
	char *gtsFile = Get_GtsFile ( gameFile );
	if ( !IsExist (gameFile) || !IsExist ( gtsFile ) )
	{
		cout << endl << "Can not build GUI, make sure exist " << gameFile << " and " << gtsFile;
		return;
	}
	BuildTemplateID ( gtsFile );
	BuildGui_LayerID ( gameFile );
	BuildAllLevel ( gameFile, gtsFile);
	BuildGuiToPack ( gameFile );
}

void main( int argv, char* agv[] ) 
{
	//BuildGui ( agv[1] );
	cout << endl;
	BuildGui ( "gui.game" );
	//system ( "pause" );
}